10.2 Training SVM mit Scikit-Learn#

Lernziele

  • Sie können ein SVM-Modell mit Scikit-Learn trainieren.

Scikit-Learn bietet mehrere Implementierungen#

Wenn wir in der Dokumentation von Scikit-Learn Scikit-Learn/SVM die Support Vector Machines nachschlagen, so finden wir drei Einträge

  • SVC,

  • NuSVC und

  • LinearSVC.

Die Beispiele des letzten Abschnittes sind linearer Natur, so dass sich eigentlich die Klasse “LinearSVC” aus Effiziengründen anbieten würde. Da wir aber im nächsten Abschnitt uns auch mit nichtlinearen Problemen beschäftigen werden, fokussieren wir uns gleich auf den SVC-Algorithmus mit seinen Optionen. NuSVC ist ähnlich zu SVC, bietet aber die zusätzliche Möglichkeit, die Anzahl der Stützvektoren einzuschränken.

Vielleicht wundern Sie sich, dass die Klasse SVC und nicht SVM heißt. Das C in SVC soll deutlich machen, dass wir die Support Vector Machines nutzen wollen, um ein Klassifikationsproblem (= Classification Problem) zu lösen.

Training mit fit und score#

Zuerst importieren wir aus Scikit-Learn das entsprechende Modul ‘SVM’ und instantiieren ein Modell. Da wir die etwas allgemeinere Klasse SVC anstatt LinearSVC verwenden, müssen wir bereits bei der Erzeugung die Option kernel= auf linear setzen, also kernel='linear'.

from sklearn import svm
svm_modell = svm.SVC(kernel='linear')

Wir erzeugen uns erneut künstliche Messdaten.

from sklearn.datasets import make_blobs
import matplotlib.pylab as plt; plt.style.use('bmh')

# generate artificial data
X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.50)

# plot artificial data
import plotly.express as px

fig = px.scatter(x = X[:,0], y = X[:,1],  color=y, color_continuous_scale=['#3b4cc0', '#b40426'],
                 title='Künstliche Daten',
                 labels={'x': 'Feature 1', 'y': 'Feature 2'})
fig.show()

Als nächstes teilen wir die Messdaten in Trainings- und Testdaten auf.

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

Nun können wir unser SVM-Modell trainieren:

svm_modell.fit(X_train, y_train);

Und als nächstes analysieren, wie viele der Testdaten mit dem trainierten Modell korrekt klassifiziert werden.

svm_modell.score(X_test, y_test)
1.0

Ein super Ergebnis! Schön wäre es jetzt noch, die gefundene Trenngerade zu visualisieren. Dazu modifizieren wir einen Code-Schnippsel aus dem Buch: »Data Science mit Python« von Jake VanderPlas (mitp Verlag 2017), ISBN 978-3-95845- 695-2, siehe jakevdp/PythonDataScienceHandbook.

# Quelle: VanderPlas "Data Science mit Python", S. 482
# modified by Simone Gramsch
import numpy as np

def plot_svc_grenze(model):
    # aktuelles Grafik-Fenster auswerten
    ax = plt.gca()
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()
    # Raster für die Auswertung erstellen
    x = np.linspace(xlim[0], xlim[1], 30)
    y = np.linspace(ylim[0], ylim[1], 30)
    Y, X = np.meshgrid(y, x)
    xy = np.vstack([X.ravel(), Y.ravel()]).T
    P = model.decision_function(xy).reshape(X.shape)
    # Entscheidungsgrenzen und Margins darstellen
    ax.contour(X, Y, P, colors='k', levels=[-1, 0, 1], alpha=0.5, linestyles=['--', '-', '--'])
    # Stützvektoren darstellen
    ax.scatter(model.support_vectors_[:, 0], model.support_vectors_[:, 1], s=300, linewidth=1, facecolors='none', edgecolors='orange');
    ax.set_xlim(xlim)
    ax.set_ylim(ylim)
fig, ax = plt.subplots()
ax.scatter(X[:,0], X[:,1], c=y, cmap='coolwarm')
ax.set_xlabel('Feature 1')
ax.set_ylabel('Feature 2')
ax.set_title('SVM mit Soft Margin');

plot_svc_grenze(svm_modell)
../_images/dc000c96388501240adf60a1d7965df12f102184999192c82352f1a1f21668d5.png

Der Parameter C#

Im letzten Abschnitt haben wir uns mit dem Parameter C beschäftigt, der Ausnahmen innerhalb des Sicherheitsstreifens erlaubt. Ein großes C bedeutet ja, dass die Wand des Margins hoch ist und kaum (oder gar keine) Punkte innerhalb des Sicherheitsstreifens liegen dürfen. Als nächstes schauen wir uns an, wie der Parameter C gesetzt wird.

Die Option zum Setzen des Parameters C lautet schlicht und einfach C=. Dabei muss C immer positiv sein.

Damit aber besser sichtbar wird, wie sich C auswirkt, vermischen wir die künstlichen Daten stärker.

# generate artificial data
X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.80)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

# plot artificial data
import plotly.express as px

fig = px.scatter(x = X[:,0], y = X[:,1],  color=y, color_continuous_scale=['#3b4cc0', '#b40426'],
                 title='Künstliche Daten',
                 labels={'x': 'Feature 1', 'y': 'Feature 2'})
fig.show()
# Wahl des Modells mit linearem Kern und großem C
svm_modell = svm.SVC(kernel='linear', C=1000000)

# Training und Bewertung
svm_modell.fit(X_train, y_train);
svm_modell.score(X_test, y_test)

# Visualisierung
fig, ax = plt.subplots()
ax.scatter(X[:,0], X[:,1], c=y, cmap='coolwarm')
ax.set_xlabel('Feature 1')
ax.set_ylabel('Feature 2')
ax.set_title('SVM mit Soft Margin');
plot_svc_grenze(svm_modell)
../_images/1cc6acf1054de8cfe8b5249cb654f2fe15f98da6bcd0e108b54be6141cd34a64.png
# Wahl des Modells mit linearem Kern und kleinem C
svm_modell = svm.SVC(kernel='linear', C=1)

# Training und Bewertung
svm_modell.fit(X_train, y_train);
svm_modell.score(X_test, y_test)

# Visualisierung
fig, ax = plt.subplots()
ax.scatter(X[:,0], X[:,1], c=y, cmap='coolwarm')
ax.set_xlabel('Feature 1')
ax.set_ylabel('Feature 2')
ax.set_title('SVM mit Soft Margin');
plot_svc_grenze(svm_modell)
../_images/ae8fb4da2ca02aaa4303db163c229fa24ee4f511c7d1b8e30c8eef4c3d1a1ba7.png

Zusammenfassung#

Verwenden wir den SVC-Klassifikator aus dem Modul SVM von Scikit-Learn, können wir mittels der Option kernel='linear' eine binäre Klassifikation durchführen, bei der die Trennungsgerade den größtmöglichen Abstand zwischen den Punkteclustern erzeugt, also einen möglichst großen Margin. Sind die Daten nicht linear trennbar, so können wir mit der Option C= steuern, wie viele Ausnahmen erlaubt werden sollen. Mit Ausnahmen sind Punkte innerhalb des Margins gemeint. Im nächsten Abschnitt betrachten wir nichtlineare Trennungsgrenzen.